package broker

import (
	"fmt"
	"gitlab.local/backend/proto/dto"
	"go-micro.dev/v4/broker"
	"google.golang.org/protobuf/proto"
	"ota/bll"
	log "ota/collector/logger"
	"ota/lib/trace_log"
	"ota/model"
	"ota/utils"
	"ota/utils/goroutine_pool"
	"strings"
)

var topics = []string{
	"signal.event.control",
	"signal.event.ota",
}

type consumer struct {
	pubSub broker.Broker
}

func NewConsumer(pubSub broker.Broker) *consumer {
	return &consumer{
		pubSub: pubSub,
	}
}

// Init 初始化
func (c *consumer) Init() error {
	for i := range topics {
		_, _ = c.pubSub.Subscribe(topics[i], c.Handle)
	}
	return nil
}

func (c *consumer) Handle(eventData broker.Event) error {

	var err error
	defer utils.ExceptionCatch()
	body := eventData.Message().Body
	switch eventData.Topic() {
	case "signal.event.control":
		err = c.handleControl(body)
		break
	case "signal.event.ota":
		var (
			t = c.checkUpgradeType(body)
		)

		switch t {
		case 1:
			err = c.handleOTAUpgradeV1(body)
		case 2:
			err = c.handleOTAUpgradeV2(body)
		default:
			return fmt.Errorf("unkown upgrade type %d", t)
		}
	}

	return err
}

func (c *consumer) handleControl(body []byte) error {
	// UpdateControl
	goroutine_pool.GetPoolV2("control").Push(nil, func(d interface{}) error {
		defer utils.ExceptionCatch()
		data := &dto.Controller{}
		err := proto.Unmarshal(body, data)
		if err != nil {
			log.Errorf("consumer handle control err:%v", err)
			return err
		}

		if data.FirmwareVersion == "" {
			trace_log.ErrorLogger.Info("中空版本上报 consumer handle control FirmwareVersion is empty sn:", data.Sn)
			log.Errorf("consumer handle control FirmwareVersion is empty sn:%s", data.Sn)
			return nil
		}

		/* BSC21 可以用通过*/
		if strings.HasPrefix(data.Sn, "BSC22") {
			return nil
		}
		// 更新设备中控版本
		trace_log.DebugLogger(data.Sn, "中控版本上报 consumer handle control FirmwareVersion:", data.FirmwareVersion)
		//bikeInfo, _ := bll.CacheBike.GetBikeInfoBySn(data.Sn)
		//if bikeInfo != nil {
		//	// 更新设备中控版本
		//	bll.Control.Update(context.Background(), &model.ControlUpdateRequest{
		//		Id:              bikeInfo.ControlId,
		//		FirmwareVersion: &data.FirmwareVersion,
		//	})
		//}
		//
		//// 同步设备信息到设备影子
		//c.SyncDeviceInfoToShadow(data.Sn, dto.EnUpdateType_ATTRIBUTE, map[string]interface{}{
		//	"firmware_version": data.FirmwareVersion,
		//})

		// 中控上报
		if err = ControlReport.HandlerControl(data); err != nil {
			log.Errorf("consumer handle HandlerControl err:%v", err)
			return err
		}

		return nil
	})

	return nil
}

func (c *consumer) checkUpgradeType(body []byte) int {

	var (
		data1 = &dto.OTAUpgradeNtf{}
		data2 = &dto.UpgradeBSC22Data{}
	)

	//fmt.Printf("%X\n", string(body))
	_ = proto.Unmarshal(body, data2)
	if data2.DeviceType != 0 && data2.Sn != "" {
		return 2
	} else {
		_ = proto.Unmarshal(body, data1)
		if data1.Sn != "" {
			return 1
		}
	}

	return 0
}

func (c *consumer) handleOTAUpgradeV1(body []byte) error {

	goroutine_pool.GetPoolV2("ota").Push(nil, func(d interface{}) error {

		defer utils.ExceptionCatch()
		var (
			data = &dto.OTAUpgradeNtf{}
			err  = proto.Unmarshal(body, data)
		)
		if err != nil {
			log.Errorf("consumer OTAUpgradeNtf handle Signal err:%v", err)
			return err
		}

		trace_log.DebugLogger(data.Sn, "OTAUpgradeNtf received:", utils.ToJsonString(data))
		// 成功
		if data.Result == 0 {

			//var (
			var version string
			//	ctx, _ = context.WithTimeout(context.Background(), time.Minute*3)
			//	vk     = &dto.GetShadowAttributeKeysResponse{}
			//)
			//vk, err = grpc.SCmd.GetShadowAttributeKeys(ctx, &dto.GetShadowAttributeKeysRequest{
			//	DeviceName: data.Sn,
			//	Key:        "firmware_version",
			//})
			//if err != nil {
			//	trace_log.DebugLogger(data.Sn, "OTAUpgradeNtf GetShadowAttributeKeys firmware_version err:", err)
			//	return err
			//}
			//
			//if vk == nil || len(vk.Value) == 0 {
			//	trace_log.DebugLogger(data.Sn, fmt.Sprintf("No version information found,sn:%v", data.Sn))
			//	return fmt.Errorf(fmt.Sprintf("No version information found,sn:%v", data.Sn))
			//}
			//version = vk.Value

			err = bll.Ota.OTAUpgradeSuccess(data, version, model.UpgradeResultFromInstructionResp)
			if err != nil {
				trace_log.DebugLogger(data.Sn, "OTAUpgradeNtf OTAUpgradeSuccess err:", err)
			}
			return nil
		}

		err = bll.Ota.OTAUpgradeFailed(data, model.UpgradeResultFromInstructionResp)
		if err != nil {
			trace_log.DebugLogger(data.Sn, "OTAUpgradeNtf OTAUpgradeFailed err:", err)
		}
		return nil
	})

	return nil
}

func (c *consumer) handleOTAUpgradeV2(body []byte) error {

	goroutine_pool.GetPoolV2("ota").Push(nil, func(d interface{}) error {
		defer utils.ExceptionCatch()
		data := &dto.UpgradeBSC22Data{}
		err := proto.Unmarshal(body, data)
		if err != nil {
			log.Errorf("consumer UpgradeBSC22Data handle Signal err:%v", err)
			return err
		}

		trace_log.DebugLogger(data.Sn, "UpgradeBSC22Data received:", utils.ToJsonString(data), "raw UpgradeBSC22Data data", fmt.Sprintf("%v", data))
		return bll.Ota.OTAUpgradeResponse(data)
	})

	return nil
}
